/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

#include <IOmenAssetManager.h>

namespace Omen {

    // Disable compiler warning C4275: non dll-interface class _X_ used as base for dll-interfac class _y_
    #pragma warning( disable: 4275 )

    /// Basic Asset object interface
    class Asset : public IAsset {
    public:
        OMEN_API virtual IAssetNode* treeNode() { return pTreeNode; }

        OMEN_API virtual std::wstring name() const { return m_name; }
        
        OMEN_API virtual bool loadAsset() = 0;               /// Loads the asset and return true if succeeded, false otherwise
        OMEN_API virtual bool releaseAsset() = 0;            /// Releases the allocated resources by this asset

        OMEN_API virtual void setType( Omen::AssetType type );
        OMEN_API virtual Omen::AssetType& type();               // Returns a reference to the asset type
        
        OMEN_API virtual std::wstring& path();            /// Returns the path of the asset
        OMEN_API virtual std::wstring& filename();        /// Returns the filename of the asset

    protected:
        std::wstring m_name;
        std::wstring assetFileName;
        std::wstring assetPath;

        Omen::AssetType assetType;

        IAssetNode* pTreeNode;

    protected:
        Asset();
    private:
    };

    /// Specific Asset object interfaces
    class OMEN_API ModelAsset : public Asset 
    {
    public:
        ModelAsset( const std::wstring& name );
        virtual ~ModelAsset();

        virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
    };
    
    class OMEN_API TextureMapAsset : public Asset 
    {
    public:
        TextureMapAsset( const std::wstring& name );
        virtual ~TextureMapAsset();

        virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
    };
    
    class OMEN_API AudioAsset : public Asset 
    {
    public:
        AudioAsset( const std::wstring& name );
        virtual ~AudioAsset();

        virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
    };

    class OMEN_API ScriptAsset : public Asset 
    {
    public:
        ScriptAsset( const std::wstring& name );
        virtual ~ScriptAsset();

        virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
    };

    class OMEN_API AnimationAsset : public Asset 
    {
    public:
        AnimationAsset( const std::wstring& name );
        virtual ~AnimationAsset();

        virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
    };

    class OMEN_API MovieAsset : public Asset 
    {
    public:
        MovieAsset( const std::wstring& name );
        virtual ~MovieAsset();

        virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
    };

    // Disable compiler warning C4275: non dll-interface class _X_ used as base for dll-interfac class _y_
    #pragma warning( default: 4275 )
    
    /// Interface object for Asset node in tree
    class AssetNode : public IAssetNode 
    {
    public:
        AssetNode( IAssetNode* pParentNode, const std::wstring& name ) : m_pParentNode(pParentNode),m_name(name), m_pAsset(NULL) {}
        
        OMEN_API virtual void addChild( IAssetNode* pChild );
        OMEN_API virtual std::wstring name() const;

        OMEN_API virtual IAssetNode* parent() const { return m_pParentNode; }
        OMEN_API virtual unsigned long getChildren( IAssetNode** children, unsigned long& maxNum );
        OMEN_API virtual IAssetNode* findChild( const std::wstring& nodeName ) const;
        OMEN_API virtual unsigned long childCount() const;
        OMEN_API virtual IAsset* asset();
        OMEN_API virtual void setAsset( IAsset* pAsset );

        OMEN_API virtual bool loadAsset();               /// Loads the asset and return true if succeeded, false otherwise
        OMEN_API virtual bool releaseAsset();            /// Releases the allocated resources by this asset
    protected:
    private:
        std::wstring    m_name;
        IAssetNode*     m_pParentNode;
        IAsset*         m_pAsset;
        std::vector<IAssetNode*> m_listChildren;
    };

    /// Asset Manager Interface class to access the assets
    class AssetManager : public IAssetManager 
    {
         #define GUID_OMEN_ASSETMANAGER "64964040-EFDE-44BF-8AA2-A9DABD599F1A"

    public:
        OMEN_API virtual Omen_GUID classId() const { return OMEN_UUID(GUID_OMEN_ASSETMANAGER); }    /// <summary>Defines the class ID</summary>

    public: 
        /// Constructors & destructor
        OMEN_API AssetManager(Omen::IObject* pParent = 0);
        /// Enumerate assets with given type in given directory and adds them to the asset manager
        OMEN_API virtual unsigned long enumerateAssets( const Omen::AssetType& type, const std::wstring& assetPath, bool recursive );

        /// Get anumerated assets of given type
        OMEN_API virtual void getAssets( const Omen::AssetType& type, std::vector<IAssetNode>& assets );

        /// Get the root node of all assets
        OMEN_API virtual void getAssets( IAssetNode& rootNode );
        
        /// Find an asset with given type and name that exactly or partially matches the given name
        OMEN_API virtual bool findAssets( const Omen::AssetType& type, const std::wstring& name, std::vector<IAssetNode*>& assets );
    
    protected:
        unsigned long AssetManager::enumerateAssetsByExtAndType( const Omen::AssetType& type, 
                                                                 std::vector<std::wstring>& assetExts, 
                                                                 const std::wstring& assetPath, 
                                                                 const std::wstring& assetNodeName,
                                                                 bool recursive );
    private:
        AssetNode* m_rootAssetNode;

    };
    
    // ----------------------------------------------------------------------- //

} // namespace Omen

/// EOF